package dm.ast;

import test.envset.GlobalState;

public class DmSelect extends DmASTNode {
    public final static int INDEX_HINT = 0; // 0 hint
    public final static int INDEX_TOP = 1;
    public final static int INDEX_ELEMENT = 2;// 1 selectElements
    public final static int INDEX_FROM = 3;// 2 from-sources
    public final static int INDEX_WHERE = 4;// 3 where-clause
    public final static int INDEX_GROUP = 5;// 4 groupby-clause
    public final static int INDEX_HAVING = 6;// 5 having-clause
    public final static int INDEX_ORDER = 7;// 6 orderby-clause
    public final static int INDEX_LIMIT = 8;// 7 limit-clause
    public final static int INDEX_ROWLIMIT = 9;
    public final static int INDEX_WITH = 10;// 9 with-statement
    // 没看懂*
    public final static int SUBCLAUSE_CNT = 11;
    public DmASTNode[] subClause = new DmASTNode[SUBCLAUSE_CNT];

    private boolean districtFlag = false;

    public void setDistrictFlag(boolean districtFlag) {
        this.districtFlag = districtFlag;
    }

    public long execTimeMS = -1; // 执行时间,单位mS

    public DmSelect() {
        for (int i = 0; i < SUBCLAUSE_CNT; i++) {
            subClause[i] = null;
        }
        wid_t = 0;
        dep_t = 1;
    }

    public void setHints(DmHint dmHint) {
        subClause[INDEX_HINT] = dmHint;
    }

    public void setSelectElements(DmSelectElements selectElements) {
        if (selectElements == null) {
            throw new IllegalArgumentException();
        }
        subClause[INDEX_ELEMENT] = selectElements;
        setComplexity();
    }

    public DmSelectElements getSelectElements() {
        return (DmSelectElements) subClause[INDEX_ELEMENT];
    }

    public void setFromList(DmFrom fromList) {
        subClause[INDEX_FROM] = fromList;
        setComplexity();
    }

    public DmFrom getFromList() {
        return (DmFrom) subClause[INDEX_FROM];
    }

    public void setWhereClause(DmWhere whereClause) {
        subClause[INDEX_WHERE] = whereClause;
        setComplexity();
    }

    public DmWhere getWhereClause() {
        return (DmWhere) subClause[INDEX_WHERE];
    }

    public void setGroupbyClause(DmGroupby groupbyClause) {
        subClause[INDEX_GROUP] = groupbyClause;
        setComplexity();
    }

    public DmGroupby getGroupbyClause() {
        return (DmGroupby) subClause[INDEX_GROUP];
    }

    public void setOrderbyClause(DmOrderby orderbyClause) {
        subClause[INDEX_ORDER] = orderbyClause;
        setComplexity();
    }

    public DmOrderby getOrderbyClause() {
        return (DmOrderby) subClause[INDEX_ORDER];
    }

    public void setHavingClause(DmHaving havingClause) {
        subClause[INDEX_HAVING] = havingClause;
        setComplexity();
    }

    public DmHaving getHavingClause() {
        return (DmHaving) subClause[INDEX_HAVING];
    }

    public void setLimitClause(DmLimit limitClause) {
        subClause[INDEX_LIMIT] = limitClause;
        setComplexity();
    }

    public DmLimit getLimitClause() {
        return (DmLimit) subClause[INDEX_LIMIT];
    }

    public void setRowLimitClause(DmRowLimit rowLimitClause) {
        subClause[INDEX_ROWLIMIT] = rowLimitClause;
        setComplexity();
    }

    public DmRowLimit getRowLimitClause() {
        return (DmRowLimit) subClause[INDEX_ROWLIMIT];
    }

    public void setTopClause(DmTop topClause) {
        //TODO
        subClause[INDEX_TOP] = topClause;
        setComplexity();
    }

    public DmTop getTopClause() {
        //TODO
        return (DmTop) subClause[INDEX_TOP];
    }

    public void setWithClause(DmWith withClause) {
        subClause[INDEX_WITH] = withClause;
        setComplexity();
    }

    public DmWith getWithClause() {
        return (DmWith) subClause[INDEX_WITH];
    }

    // 设置属性列的starFlag
    private void setSelElementsStarFlag(boolean starFlag) {
        if (subClause[INDEX_ELEMENT] != null) {
            DmSelectElements tmp = (DmSelectElements) subClause[INDEX_ELEMENT];
            tmp.starFlag = starFlag;
        }
    }

    public void setStarFlag(boolean starFlag) {
        if (starFlag && subClause[INDEX_FROM] != null) {
            setSelElementsStarFlag(true);
        } else {
            setSelElementsStarFlag(false);
        }
    }

    // 将select语句部分所有子句的wid_t累加,就是该select语句的wid_t
    // 注意, 初始为1, 因为有select关键字。
    @Override
    public void setWidt() {
        wid_t = 1;
        for (int i = 1; i < SUBCLAUSE_CNT; i++) {
            if (subClause[i] != null) {
                subClause[i].setWidt();
                wid_t += subClause[i].wid_t;
            }
        }
    }

    // 取select语句部分所有子句的dep_t中的最大值, 就是该select语句的dep_t
    // 注意,初始为1,
    @Override
    public void setDept() {
        int tmpMAXdept = 1;
        for (int i = 1; i < SUBCLAUSE_CNT; i++) {
            if (subClause[i] != null) {
                subClause[i].setDept();
                if (subClause[i].dep_t > tmpMAXdept) {
                    tmpMAXdept = subClause[i].dep_t;
                }
            }
        }
        dep_t = tmpMAXdept;
    }

    @Override
    public DmDataType getExpressionType() {
        return getSelectElements().getExpressionType();
    }

    @Override
    public String toSql() {
        StringBuilder sql = new StringBuilder();
        // 首先处理with子句
        if (subClause[INDEX_WITH] != null) {
            // 将其转换为sql字符串并添加到sql中
            sql.append(subClause[INDEX_WITH].toSql());
        }
        // 拼接sql
        sql.append("SELECT " + getSqlTarget() + getSqlComplexity());
        if (districtFlag) {
            sql.append(" DISTINCT ");
        }
        // 使用for循环处理其他子句
        for (int i = 0; i < SUBCLAUSE_CNT - 1; i++) { // 需要-1, 是因为末尾的with子句已经处理
            if (subClause[i] != null) {
                sql.append(subClause[i].toSql());
            }
        }
        // 把StringBuilder对象转换为String并返回StringBuilder
        return sql.toString();
    }

    // 实现填充, 利用元数据完成节点生成
    @Override
    public void fill(GlobalState globalState) {
        if (!isCompleted) {
            globalState.initFillSelect();
            //如果有with子句, 那么先完成with子句填充
            if (subClause[INDEX_WITH] != null) {
                subClause[INDEX_WITH].fill(globalState);
                //将with子句的CTES加入缓冲区, 以便使用
                globalState.buildWithCTES(getWithClause());
            }
            //先完成from子句填充
            if (subClause[INDEX_FROM] != null) {
                subClause[INDEX_FROM].fill(globalState);
            }
            //后续完成其它部分填充
            if (subClause[INDEX_HINT] != null) {
                subClause[INDEX_HINT].fill(globalState);
            }
            if(subClause[INDEX_TOP] != null){
                subClause[INDEX_TOP].fill(globalState);
            }
            if (subClause[INDEX_ELEMENT] != null) {
                subClause[INDEX_ELEMENT].fill(globalState);
            }
            if (subClause[INDEX_WHERE] != null) {
                subClause[INDEX_WHERE].fill(globalState);
            }
            if (subClause[INDEX_GROUP] != null) {
                int groups = ((DmGroupby) subClause[INDEX_GROUP]).fillBySelElement((DmSelectElements) subClause[INDEX_ELEMENT]);
                if (groups != 0) {
                    //需要处理非分组项的查询列。要么删除,要么增加集函数
                    ((DmSelectElements) subClause[INDEX_ELEMENT]).dealGroupy(groups);
                } else { //没有分组项,删除groupbx子句
                    subClause[INDEX_GROUP] = null;
                }
            }
            if (subClause[INDEX_ORDER] != null) {
                int groups = 0;
                //有groupby语句,只能从查询列中选；没有groupby子句,可以从表列名中选
                groups = ((DmOrderby) subClause[INDEX_ORDER]).fillBySelElement(globalState, (DmSelectElements) subClause[INDEX_ELEMENT]);
                //orderby子句实际拥有的排序项数目为0, 子句不存在
                if (groups == 0) {
                    subClause[INDEX_ORDER] = null;
                }
            }
            if (subClause[INDEX_HAVING] != null) {
                if(subClause[INDEX_GROUP] == null){
                    //groupby子句为空，那么having子句也值为空，否则容易出现错误
                    subClause[INDEX_HAVING] = null;
                }else {
                    subClause[INDEX_HAVING].fill(globalState);
                }
            }
            if (subClause[INDEX_LIMIT] != null) {
                subClause[INDEX_LIMIT].fill(globalState);
            }
            if (subClause[INDEX_ROWLIMIT] != null) {
                subClause[INDEX_ROWLIMIT].fill(globalState);
            }

            globalState.finishFillSelect(getWithClause());
            if(globalState.getWithFinishFlag()){
                //如果with中的CTE都没有使用,那么就去掉with子句
                if (subClause[INDEX_WITH] != null) {
                    setWithClause(getWithClause().buildNewDmWith());
                }
            }
            setWidt();
            setDept();
            isCompleted = true;

        }
    }

    // 处理与gl错误
    // -4097|单行子查询返回多行
    public void fixErr4097() {
        ((DmSelectElements) subClause[INDEX_ELEMENT]).fixErr4097();
        if (subClause[INDEX_FROM] != null) {
            ((DmFrom) subClause[INDEX_FROM]).fixErr4097();
        }
        if (subClause[INDEX_WHERE] != null) {
            ((DmWhere) subClause[INDEX_WHERE]).fixErr4097();
        }
        if (subClause[INDEX_HAVING] != null) {
            ((DmHaving) subClause[INDEX_HAVING]).fixErr4097();
        }
        if (subClause[INDEX_WITH] != null) {
            ((DmWith) subClause[INDEX_WITH]).fixErr4097();
        }
        if (sel_level > 0) {
            if (subClause[INDEX_LIMIT] != null) {
                subClause[INDEX_LIMIT] = null;
            }
            if (subClause[INDEX_ROWLIMIT] != null) {
                subClause[INDEX_ROWLIMIT] = null;
            }
            if (subClause[INDEX_TOP] != null) {
                ((DmTop) subClause[INDEX_TOP]).fixErr4097();
            } else {
                DmTop topFix = new DmTop();
                topFix.m = 1;
                topFix.n = 0;
                subClause[INDEX_TOP] = topFix;
            }
        }
    }
}